Unreal Texture Filtration.

upi/throb

Algorithm.

Unreal texture filtration is very simple, in a fact it's table bilinear filtration, and it can easily be included in every inner loop.

Let's define this table:

                          +----------+-----------+
		       Y\X|   even   |    odd    |
		        e +----------+-----------+
		        v | du = .25 | du = 0    |
		        e | dv = .75 | dv = .50  |
		        n |          |           |
		        - +----------+-----------+
		        o | du = .50 | du = .75  |
		        d | dv = 0   | dv = .25  |
		        d |          |           |
		          +----------+-----------+

du,dv - texture correction values for U and V,
"even" - even X/Y(on screen),
"odd" - odd X/Y

Algorithm:

1. get screen X,Y (usually it exists in the inner loop)

2. looks in our table, get du,dv

3. correct texture coordinates U,V

(they must be float or fixed point, otherwise the algorithm won't work)

4. put texel on screen.

5. your code =)

6. goto 1.

Optimization.

Every coder understands that looking up every texel in a table is really slow. I found a solution while debugging my code. =) In the scanline drawing routine I carefully watched my variables du and dv. They changed like (0.25,0.75), (0.0,0.50), (0.25,0.75), (0.0,0.50),... hmm. Systematic... 0.25 goes to 0.0 and back, and 0.75 goes to 0.50 and back to 0.75. Flash! Wow! It's a simple XOR!

In a fixedpoint loop you must just XOR "start" du,dv with a constant value and add the result to U and V. "start" du,dv are taken from our table on entering the scanline loop!

Sample code.

Here's a scanline filling code with perspective correction and zbuffer (in fact it's only the part that does the filling of the remainder of affine subdivision of the scanline by 16 pixels). For U and V I use 8:8 fixedpoint.

;scanline enter 
;eax - X*4
;esi - Y
ifdef filtering
	shr eax,2  				;get start order
	and eax,1
	mov ebx,esi
	and ebx,1
	shl ebx,2
	add ebx,eax

	mov dh,byte ptr _orderTab[ebx*4]	;our table
	mov dl,byte ptr _orderTab[ebx*4 + 4]
endif

	mov ecx,dword ptr _Inner1Count
	xor eax,eax
	xor ebx,ebx
dsall66:					;inner loop
	fld dword ptr _256
	fdiv st(0),st(1)

	fld st(0)
	fmul dword ptr _Ze
	fistp dword ptr _Zs			;zbuff

	fld st(0)				;(1/z)/(1/z)/z/v/u...
	fmul st(0),st(3)
	fistp dword ptr _Vs
	fmul st(0),st(3)
	fistp dword ptr _Us

	or ecx,ecx
	jz dsall67

ZZZsm1:
	mov eax,dword ptr [edi + 12345678h]	;zbuffer
	mov ebx,dword ptr _Zs
	add ebx,05000h
	cmp eax,ebx
;	jl dZl1
	jb dZl1
ZZZsm2:
	xor eax,eax
	mov ax,word ptr _Vs
ifdef filtering
	add al,dl                               ;add dv
	adc ah,0
endif
	xor ebx,ebx
	shr ax,8

	mov bx,word ptr _Us
ifdef filtering					
	add bl,dh                               ;add du
	adc bh,0
endif
	shr bx,8
	add ebx,dword ptr _YTab[eax*4]
SMpt2:
	mov ebx,dword ptr [ebx*4 + 12345678h]

	mov dword ptr [edi],ebx

dZl1:
	fld dword ptr _C.y
	faddp st(1),st(0)
	fld dword ptr _B.y
	faddp st(2),st(0)
	fld dword ptr _A.y
	faddp st(3),st(0)

	add edi,4
ifdef filtering
	xor dx,0c0c0h				;!!!!!!!!!!!!!!!!!
endif						;adjust du and dv!
	dec ecx
	jmp dsall66

Happy coding.

upi/throb